package ultis

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"math/rand"
	// "github.com/u2takey/go-ffmpeg"
)

// 自定义排序函数，按照文件名中的数字大小排序
type ByNumericFilename []string

func (f ByNumericFilename) Len() int      { return len(f) }
func (f ByNumericFilename) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f ByNumericFilename) Less(i, j int) bool {
	num1, err1 := extractNumber(f[i])
	num2, err2 := extractNumber(f[j])
	if err1 == nil && err2 == nil {
		return num1 < num2
	}
	return f[i] < f[j]
}

// 从文件名中提取数字
func extractNumber(filename string) (int, error) {
	// 使用正则表达式提取数字部分
	re := regexp.MustCompile(`\d+`)
	matches := re.FindAllString(filename, -1)
	if len(matches) == 0 {
		return 0, fmt.Errorf("no number found in filename")
	}
	// 将提取的数字转换为整数
	return strconv.Atoi(matches[len(matches)-1])
}

// 读取指定文件夹中的所有文件并进行排序
func getFiles(folderPath string) ([]string, error) {
	entries, err := os.ReadDir(folderPath)
	if err != nil {
		return nil, err
	}

	var files []string
	for _, entry := range entries {
		if !entry.IsDir() {
			files = append(files, filepath.Join(folderPath, entry.Name()))
		}
	}

	// 对文件进行排序
	sort.Sort(ByNumericFilename(files))

	return files, nil
}

// 创建一个临时文件列表 filelist.txt，其中包含所有 .ts 文件的路径
func createTempFileList(files []string) (string, error) {
	tempFileList, err := os.Create("filelist.txt")
	if err != nil {
		return "", err
	}
	defer tempFileList.Close()

	// 获取文件的绝对路径
	absPath, err := filepath.Abs(tempFileList.Name())
	if err != nil {
		fmt.Println("Error getting absolute path:", err)
		return "", err
	}

	for _, file := range files {
		_, err := tempFileList.WriteString(fmt.Sprintf("file '%s'\n", file))
		if err != nil {
			return "", err
		}
	}
	return absPath, nil
}

// 使用 ffmpeg 命令将这些 .ts 文件合成为一个 MP4 文件
func mergeTSFilesToMP4ByCmd(tempFileList string, outputFile string) error {
	cmd := exec.Command("ffmpeg", "-f", "concat", "-safe", "0", "-ignore_unknown", "-i", tempFileList, "-c", "copy", outputFile)
	fmt.Print(cmd.String())
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

// // 使用 go-ffmpeg 库将这些 .ts 文件合成为一个 MP4 文件
// func mergeTSFilesToMP4(tempFileList string, outputFile string) error {
// 	// 创建 ffmpeg 实例
// 	ffmpegInstance := ffmpeg.New()

// 	// 设置输入文件列表
// 	err := ffmpegInstance.Input(tempFileList).
// 		WithOption("-f", "concat").
// 		WithOption("-safe", "0").
// 		Output(outputFile).
// 		WithOption("-c", "copy").
// 		Run()

// 	if err != nil {
// 		return err
// 	}

// 	return nil
// }

// ensureMP4Extension 确保字符串以 .mp4 结尾，如果不是则添加 .mp4
func ensureMP4Extension(str string) string {
	if !strings.HasSuffix(str, ".mp4") {
		str += ".mp4"
	}
	return str
}

func MergeVedioFile(folderPath string, outputFile string) (bool, error) {
	outputFile = ensureMP4Extension(outputFile)

	// 1. 读取指定文件夹中的所有 .ts 文件并进行排序
	files, err := getFiles(folderPath)
	if err != nil {
		return false, err
	}

	// 2. 创建一个包含所有 .ts 文件路径的长字符串
	fileList, err := createTempFileList(files)
	if err != nil {
		return false, err
	}
	defer os.Remove(fileList) // 删除临时文件列表

	// 3. 使用 ffmpeg 命令将这些 .ts 文件合成为一个 MP4 文件
	err = mergeTSFilesToMP4ByCmd(fileList, outputFile)
	if err != nil {
		return false, err
	}

	return true, nil
}

// SanitizeFilename 将字符串转换为合法的文件名
func SanitizeFilename(filename string) string {
	// 定义非法字符的正则表达式
	illegalChars := regexp.MustCompile(`[\\/:*?"<>|]`)

	// 替换非法字符为下划线
	sanitized := illegalChars.ReplaceAllString(filename, "_")

	// 去掉前后的空格
	sanitized = strings.TrimSpace(sanitized)

	// 限制文件名长度，假设最大长度为 255 字符
	const maxLength = 255
	if len(sanitized) > maxLength {
		sanitized = sanitized[:maxLength]
	}

	return sanitized
}

// 带检测的创建文件夹路径的方法
func CreateDirectory(path string) error {
	// 检查路径是否存在
	_, err := os.Stat(path)
	if err == nil {
		// 路径存在，检查目录是否为空
		entries, err := os.ReadDir(path)
		if err != nil {
			return fmt.Errorf("failed to read directory: %w", err)
		}
		if len(entries) > 0 {
			return fmt.Errorf("directory '%s' already exists and is not empty", path)
		}
		// fmt.Printf("Directory '%s' already exists but is empty.\n", path)
		return nil
	} else if os.IsNotExist(err) {
		// 路径不存在，创建目录
		err := os.MkdirAll(path, 0755)
		if err != nil {
			return fmt.Errorf("failed to create directory: %w", err)
		}
		// fmt.Printf("Directory '%s' created successfully.\n", path)
		return nil
	} else {
		// 其他错误
		return fmt.Errorf("error checking directory: %w", err)
	}
}

// GenerateRandomString generates a random string of the specified length
func GenerateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))

	b := make([]byte, length)
	for i := range b {
		b[i] = charset[seededRand.Intn(len(charset))]
	}
	return string(b)
}
